#include "EvaluationHandler.h"
#include "Cpu.h"
#include "..\Manager\MultiPostManager.h"
#include "..\Manager\SignatureManager.h"
#include "..\Manager\TeacherManager.h"

using namespace std;

namespace TCServer
{
    namespace RPHandler
    {
        EvaluationHandler* EvaluationHandler::_instance = nullptr;

        EvaluationHandler::EvaluationHandler()
        {
            assert(_instance == nullptr);

            setOn("evaluation/multi/fetch/newer", this, &EvaluationHandler::queryNewerMultiPost);
            setOn("evaluation/multi/fetch/older", this, &EvaluationHandler::queryOlderMultiPost);
			setOn("evaluation/multi/new/image", this, &EvaluationHandler::newMultiPostImage);
			setOn("evaluation/multi/new/audio", this, &EvaluationHandler::newMultiPostAudio);
			setOn("evaluation/p2p/teacherGroups/fetch", this, &EvaluationHandler::queryTeacherGroups);
            _instance = this;
        }

        EvaluationHandler::~EvaluationHandler()
        {
            _instance = nullptr;
        }

        void EvaluationHandler::queryNewerMultiPost(QDataStream &stream, QVariantMap args)
        {
            auto res = Manager::SignatureManager::instance()->check(args.value("signature").toByteArray());

            if (get<bool>(res))
			{
				auto &permissions = get<QSet<Type::Permission>>(res);

				if (permissions.contains(Type::Permission::User))
				{
					auto time = args.value("time").toDateTime();
					auto number = args.value("number").toUInt();

					number = min(number, 10u);

					auto res = Manager::MultiPostManager::instance()->queryNewer(time, number);

					stream << true << res;
				}
                    return;
            }
            stream << false;
        }

        void EvaluationHandler::queryOlderMultiPost(QDataStream &stream, QVariantMap args)
        {
            auto res = Manager::SignatureManager::instance()->check(args.value("signature").toByteArray());

            if (get<bool>(res))
			{
				auto &permissions = get<QSet<Type::Permission>>(res);

				if (permissions.contains(Type::Permission::User))
				{
					auto time = args.value("time").toDateTime();
					auto number = args.value("number").toUInt();

					number = min(number, 10u);

					auto res = Manager::MultiPostManager::instance()->queryOlder(time, number);

					stream << true << res;
					return;
				}
            }
            stream << false;

        }

        void EvaluationHandler::newMultiPostImage(QDataStream &stream, QVariantMap args)
        {
            auto res = Manager::SignatureManager::instance()->check(args.value("signature").toByteArray());

            if (get<bool>(res))
            {
                auto userId = get<quint64>(res);
                auto &permissions = get<QSet<Type::Permission>>(res);

                if (permissions.contains(Type::Permission::User))
                {
                    auto type = args.value("type").toString();
                    auto imageCount = args.value("imageCount").toString();
                    auto mainImage = args.value("mainImage").toString();
                    auto comment = args.value("comment").toString();

                    stream << Manager::MultiPostManager::instance()->
                        newPost(userId,
                            type,
                            imageCount,
                            mainImage,
                            "", 
                            comment);
                    return;
                }
            }
            else
            {
                stream << false;
            }
        }

        void EvaluationHandler::newMultiPostAudio(QDataStream &stream, QVariantMap args)
        {
            auto res = Manager::SignatureManager::instance()->check(args.value("signature").toByteArray());

            if (get<bool>(res))
            {
                auto userId = get<quint64>(res);
                auto &permissions = get<QSet<Type::Permission>>(res);

                if (permissions.contains(Type::Permission::User))
                {
                    auto type = args.value("type").toString();
                    auto audioSouce = args.value("audioSource").toString();
                    auto comment = args.value("comment").toString();

                    stream << Manager::MultiPostManager::instance()->
                        newPost(userId,
                            type,
                            0,
                            "",
                            audioSouce,
                            comment);
                    return;
                }
            }
            else
            {
                stream << false;
            }
        }

		void EvaluationHandler::queryTeacherGroups(QDataStream &stream, QVariantMap args)
		{
			auto res = Manager::SignatureManager::instance()->check(args.value("signature").toByteArray());

			if (get<bool>(res))
			{
				auto &permissions = get<QSet<Type::Permission>>(res);

				if (permissions.contains(Type::Permission::User))
				{
					auto idBegin = args.value("idBegin").toUInt();
					auto idEnd = args.value("idEnd").toUInt();

					const int maxNumber = 10u;
					idEnd = min(idEnd, idBegin + maxNumber);

					auto res = Manager::TeacherManager::instance()->queryGroups(idBegin, idEnd);

					stream << true << res;
					return;
				}
			}
			stream << false;
		}

		void EvaluationHandler::queryTeachers(QDataStream &stream, QVariantMap args)
		{
			throw std::logic_error("This method is not implemented.");
			auto res = Manager::SignatureManager::instance()->check(args.value("signature").toByteArray());

			if (get<bool>(res))
			{
				auto &permissions = get<QSet<Type::Permission>>(res);

				if (permissions.contains(Type::Permission::User))
				{
					auto groupId = args.value("groupId").toULongLong();
					auto idBegin = args.value("idBegin").toULongLong();
					auto idEnd = args.value("idEnd").toULongLong();

					const int maxNumber = 10u;
					idEnd = min(idEnd, idBegin + maxNumber);

                    auto res = Manager::TeacherManager::instance()->queryTeachers(groupId, idBegin, idEnd);

					stream << true << res;
					return;
				}
			}
			stream << false;
		}

		EvaluationHandler* EvaluationHandler::instance()
        {
            if (_instance == nullptr)
                _instance = new EvaluationHandler;
            return _instance;
        }

    }

}